/*
* Atlas.cs
*
* BLAS provider for the ATLAS library.
*
* Copyright (c) 2005, dnAnalytics. All rights reserved.
*/

#region Using Directives
using dnAnalytics.Math;
using dnAnalytics.LinearAlgebra.Native;
#endregion


namespace dnAnalytics.LinearAlgebra.Native.AtlasClapack
{
    internal sealed class Blas : IBlas
    {
        private static readonly IBlas instance = new Blas();

        private Blas() { }

        #region Public Members

        public static IBlas Instance
        {
            get { return instance; }
        }

        public double Ddot(int n, double[] x, int incX, double[] y, int incY)
        {
            return SafeNativeMethods.cblas_ddot(n, x, incX, y, incY);
        }

        public Complex Zdotu_sub(int n, Complex[] x, int incX, Complex[] y, int incY)
        {
            Complex dotu = new Complex();
            SafeNativeMethods.cblas_zdotu_sub(n, x, incX, y, incY, ref dotu);
            return dotu;
        }

        public Complex Zdotc_sub(int n, Complex[] x, int incX, Complex[] y, int incY)
        {
            Complex dotc = new Complex();
            SafeNativeMethods.cblas_zdotc_sub(n, x, incX, y, incY, ref dotc);
            return dotc;
        }

        public double Dnrm2(int n, double[] x, int incX)
        {
            return SafeNativeMethods.cblas_dnrm2(n, x, incX);
        }

        public double Dasum(int n, double[] x, int incX)
        {
            return SafeNativeMethods.cblas_dasum(n, x, incX);
        }

        public double Dznrm2(int n, Complex[] x, int incX)
        {
            return SafeNativeMethods.cblas_dznrm2(n, x, incX);
        }

        public double Dzasum(int n, Complex[] x, int incX)
        {
            return SafeNativeMethods.cblas_dzasum(n, x, incX);
        }

        public int Idamax(int n, double[] x, int incX)
        {
            return SafeNativeMethods.cblas_idamax(n, x, incX);
        }

        public int Izamax(int n, Complex[] x, int incX)
        {
            return SafeNativeMethods.cblas_izamax(n, x, incX);
        }

        public void Dswap(int n, double[] x, int incX, double[] y, int incY)
        {
            SafeNativeMethods.cblas_dswap(n, x, incX, y, incY);
        }

        public void Dcopy(int n, double[] x, int incX, double[] y, int incY)
        {
            SafeNativeMethods.cblas_dcopy(n, x, incX, y, incY);
        }

        public void Daxpy(int n, double alpha, double[] x, int incX, double[] y, int incY)
        {
            SafeNativeMethods.cblas_daxpy(n, alpha, x, incX, y, incY);
        }

        public void Drotg(ref double a, ref double b, out double c, out double s)
        {
            SafeNativeMethods.cblas_drotg(ref a, ref b, out c, out s);
        }

        public void Zswap(int n, Complex[] x, int incX, Complex[] y, int incY)
        {
            SafeNativeMethods.cblas_zswap(n, x, incX, y, incY);
        }

        public void Zcopy(int n, Complex[] x, int incX, Complex[] y, int incY)
        {
            SafeNativeMethods.cblas_zcopy(n, x, incX, y, incY);
        }

        public void Zaxpy(int n, Complex alpha, Complex[] x, int incX, Complex[] y, int incY)
        {
            SafeNativeMethods.cblas_zaxpy(n, ref alpha, x, incX, y, incY);
        }

        public void Zrotg(ref Complex a, ref Complex b, out Complex c, out Complex s)
        {
            SafeNativeMethods.cblas_zrotg(ref a, ref b, out c, out s);
        }

        public void Drotmg(ref double d1, ref double d2, ref double x1, double y1, out double[] p)
        {
            p = new double[5];
            SafeNativeMethods.cblas_drotmg(ref d1, ref d2, ref x1, y1, p);
        }

        public void Drot(int n, double[] x, int incX, double[] y, int incY, double c, double s)
        {
            SafeNativeMethods.cblas_drot(n, x, incX, y, incY, c, s);
        }

        public void Drotm(int n, double[] x, int incX, double[] y, int incY, double[] p)
        {
            SafeNativeMethods.cblas_drotm(n, x, incX, y, incY, p);
        }

        public void Zdrot(int n, Complex[] x, int incX, Complex[] y, int incY, double c, double s)
        {
            SafeNativeMethods.cblas_zdrot(n, x, incX, y, incY, c, s);
        }

        public void Dscal(int n, double alpha, double[] x, int incX)
        {
            SafeNativeMethods.cblas_dscal(n, alpha, x, incX);
        }

        public void Zscal(int n, Complex alpha, Complex[] x, int incX)
        {
            SafeNativeMethods.cblas_zscal(n, ref alpha, x, incX);
        }

        public void Zdscal(int n, double alpha, Complex[] x, int incX)
        {
            SafeNativeMethods.cblas_zdscal(n, alpha, x, incX);
        }
        public void Dgemv(BlasOrderType order, BlasTransType transA, int m, int n, double alpha, double[] a, int lda, double[] x, int incX, double beta, double[] y, int incY)
        {
            SafeNativeMethods.cblas_dgemv(order, transA, m, n, alpha, a, lda, x, incX, beta, y, incY);
        }

        public void Dgbmv(BlasOrderType order, BlasTransType transA, int m, int n, int kl, int ku, double alpha, double[] a, int lda, double[] x, int incX, double beta, double[] y, int incY)
        {
            SafeNativeMethods.cblas_dgbmv(order, transA, m, n, kl, ku, alpha, a, lda, x, incX, beta, y, incY);
        }

        public void Dtrmv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, double[] a, int lda, double[] x, int incX)
        {
            SafeNativeMethods.cblas_dtrmv(order, uplo, transA, diag, n, a, lda, x, incX);
        }

        public void Dtbmv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, int k, double[] a, int lda, double[] x, int incX)
        {
            SafeNativeMethods.cblas_dtbmv(order, uplo, transA, diag, n, k, a, lda, x, incX);
        }

        public void Dtpmv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, double[] ap, double[] x, int incX)
        {
            SafeNativeMethods.cblas_dtpmv(order, uplo, transA, diag, n, ap, x, incX);
        }

        public void Dtrsv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, double[] a, int lda, double[] x, int incX)
        {
            SafeNativeMethods.cblas_dtrsv(order, uplo, transA, diag, n, a, lda, x, incX);
        }

        public void Dtbsv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, int k, double[] a, int lda, double[] x, int incX)
        {
            SafeNativeMethods.cblas_dtbsv(order, uplo, transA, diag, n, k, a, lda, x, incX);
        }

        public void Dtpsv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, double[] ap, double[] x, int incX)
        {
            SafeNativeMethods.cblas_dtpsv(order, uplo, transA, diag, n, ap, x, incX);
        }

        public void Zgemv(BlasOrderType order, BlasTransType transA, int m, int n, Complex alpha, Complex[] a, int lda, Complex[] x, int incX, Complex beta, Complex[] y, int incY)
        {
            SafeNativeMethods.cblas_zgemv(order, transA, m, n, ref alpha, a, lda, x, incX, ref beta, y, incY);
        }

        public void Zgbmv(BlasOrderType order, BlasTransType transA, int m, int n, int kl, int ku, Complex alpha, Complex[] a, int lda, Complex[] x, int incX, Complex beta, Complex[] y, int incY)
        {
            SafeNativeMethods.cblas_zgbmv(order, transA, m, n, kl, ku, ref alpha, a, lda, x, incX, ref beta, y, incY);
        }

        public void Ztrmv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, Complex[] a, int lda, Complex[] x, int incX)
        {
            SafeNativeMethods.cblas_ztrmv(order, uplo, transA, diag, n, a, lda, x, incX);
        }

        public void Ztbmv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, int k, Complex[] a, int lda, Complex[] x, int incX)
        {
            SafeNativeMethods.cblas_ztbmv(order, uplo, transA, diag, n, k, a, lda, x, incX);
        }

        public void Ztpmv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, Complex[] ap, Complex[] x, int incX)
        {
            SafeNativeMethods.cblas_ztpmv(order, uplo, transA, diag, n, ap, x, incX);
        }

        public void Ztrsv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, Complex[] a, int lda, Complex[] x, int incX)
        {
            SafeNativeMethods.cblas_ztrsv(order, uplo, transA, diag, n, a, lda, x, incX);
        }

        public void Ztbsv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, int k, Complex[] a, int lda, Complex[] x, int incX)
        {
            SafeNativeMethods.cblas_ztbsv(order, uplo, transA, diag, n, k, a, lda, x, incX);
        }

        public void Ztpsv(BlasOrderType order, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int n, Complex[] ap, Complex[] x, int incX)
        {
            SafeNativeMethods.cblas_ztpsv(order, uplo, transA, diag, n, ap, x, incX);
        }

        public void Dsymv(BlasOrderType order, BlasUpLoType uplo, int n, double alpha, double[] a, int lda, double[] x, int incX, double beta, double[] y, int incY)
        {
            SafeNativeMethods.cblas_dsymv(order, uplo, n, alpha, a, lda, x, incX, beta, y, incY);
        }


        public void Dsbmv(BlasOrderType order, BlasUpLoType uplo, int n, int k, double alpha, double[] a, int lda, double[] x, int incX, double beta, double[] y, int incY)
        {
            SafeNativeMethods.cblas_dsbmv(order, uplo, n, k, alpha, a, lda, x, incX, beta, y, incY);
        }

        public void Dspmv(BlasOrderType order, BlasUpLoType uplo, int n, double alpha, double[] ap, double[] x, int incX, double beta, double[] y, int incY)
        {
            SafeNativeMethods.cblas_dspmv(order, uplo, n, alpha, ap, x, incX, beta, y, incY);
        }

        public void Dger(BlasOrderType order, int m, int n, double alpha, double[] x, int incX, double[] y, int incY, double[] a, int lda)
        {
            SafeNativeMethods.cblas_dger(order, m, n, alpha, x, incX, y, incY, a, lda);
        }

        public void Dsyr(BlasOrderType order, BlasUpLoType uplo, int n, double alpha, double[] x, int incX, double[] a, int lda)
        {
            SafeNativeMethods.cblas_dsyr(order, uplo, n, alpha, x, incX, a, lda);
        }

        public void Dspr(BlasOrderType order, BlasUpLoType uplo, int n, double alpha, double[] x, int incX, double[] ap)
        {
            SafeNativeMethods.cblas_dspr(order, uplo, n, alpha, x, incX, ap);
        }

        public void Dsyr2(BlasOrderType order, BlasUpLoType uplo, int n, double alpha, double[] x, int incX, double[] y, int incY, double[] a, int lda)
        {
            SafeNativeMethods.cblas_dsyr2(order, uplo, n, alpha, x, incX, y, incY, a, lda);
        }

        public void Dspr2(BlasOrderType order, BlasUpLoType uplo, int n, double alpha, double[] x, int incX, double[] y, int incY, double[] a)
        {
            SafeNativeMethods.cblas_dspr2(order, uplo, n, alpha, x, incX, y, incY, a);
        }

        public void Zhemv(BlasOrderType order, BlasUpLoType uplo, int n, Complex alpha, Complex[] a, int lda, Complex[] x, int incX, Complex beta, Complex[] y, int incY)
        {
            SafeNativeMethods.cblas_zhemv(order, uplo, n, ref alpha, a, lda, x, incX, ref beta, y, incY);
        }


        public void Zhbmv(BlasOrderType order, BlasUpLoType uplo, int n, int k, Complex alpha, Complex[] a, int lda, Complex[] x, int incX, Complex beta, Complex[] y, int incY)
        {
            SafeNativeMethods.cblas_zhbmv(order, uplo, n, k, ref alpha, a, lda, x, incX, ref beta, y, incY);
        }


        public void Zhpmv(BlasOrderType order, BlasUpLoType uplo, int n, Complex alpha, Complex[] ap, Complex[] x, int incX, Complex beta, Complex[] y, int incY)
        {
            SafeNativeMethods.cblas_zhpmv(order, uplo, n, ref alpha, ap, x, incX, ref beta, y, incY);
        }

        public void Zgeru(BlasOrderType order, int m, int n, Complex alpha, Complex[] x, int incX, Complex[] y, int incY, Complex[] a, int lda)
        {
            SafeNativeMethods.cblas_zgeru(order, m, n, ref alpha, x, incX, y, incY, a, lda);
        }

        public void Zgerc(BlasOrderType order, int m, int n, Complex alpha, Complex[] x, int incX, Complex[] y, int incY, Complex[] a, int lda)
        {
            SafeNativeMethods.cblas_zgerc(order, m, n, ref alpha, x, incX, y, incY, a, lda);
        }

        public void Zher(BlasOrderType order, BlasUpLoType uplo, int n, double alpha, Complex[] x, int incX, Complex[] a, int lda)
        {
            SafeNativeMethods.cblas_zher(order, uplo, n, alpha, x, incX, a, lda);
        }

        public void Zhpr(BlasOrderType order, BlasUpLoType uplo, int n, double alpha, Complex[] x, int incX, Complex[] a)
        {
            SafeNativeMethods.cblas_zhpr(order, uplo, n, alpha, x, incX, a);
        }

        public void Zher2(BlasOrderType order, BlasUpLoType uplo, int n, Complex alpha, Complex[] x, int incX, Complex[] y, int incY, Complex[] a, int lda)
        {
            SafeNativeMethods.cblas_zher2(order, uplo, n, ref alpha, x, incX, y, incY, a, lda);
        }

        public void Zhpr2(BlasOrderType order, BlasUpLoType uplo, int n, Complex alpha, Complex[] x, int incX, Complex[] y, int incY, Complex[] ap)
        {
            SafeNativeMethods.cblas_zhpr2(order, uplo, n, ref alpha, x, incX, y, incY, ap);
        }

        public void Dgemm(BlasOrderType order, BlasTransType transA, BlasTransType transB, int m, int n, int k, double alpha, double[] a, int lda, double[] b, int ldb, double beta, double[] c, int ldc)
        {
            SafeNativeMethods.cblas_dgemm(order, transA, transB, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc);
        }

        public void Dsymm(BlasOrderType order, BlasSideType side, BlasUpLoType uplo, int m, int n, double alpha, double[] a, int lda, double[] b, int ldb, double beta, double[] c, int ldc)
        {
            SafeNativeMethods.cblas_dsymm(order, side, uplo, m, n, alpha, a, lda, b, ldb, beta, c, ldc);
        }

        public void Dsyrk(BlasOrderType order, BlasUpLoType uplo, BlasTransType trans, int n, int k, double alpha, double[] a, int lda, double beta, double[] c, int ldc)
        {
            SafeNativeMethods.cblas_dsyrk(order, uplo, trans, n, k, alpha, a, lda, beta, c, ldc);
        }

        public void Dsyr2k(BlasOrderType order, BlasUpLoType uplo, BlasTransType trans, int n, int k, double alpha, double[] a, int lda, double[] b, int ldb, double beta, double[] c, int ldc)
        {
            SafeNativeMethods.cblas_dsyr2k(order, uplo, trans, n, k, alpha, a, lda, b, ldb, beta, c, ldc);
        }

        public void Dtrmm(BlasOrderType order, BlasSideType side, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int m, int n, double alpha, double[] a, int lda, double[] b, int ldb)
        {
            SafeNativeMethods.cblas_dtrmm(order, side, uplo, transA, diag, m, n, alpha, a, lda, b, ldb);
        }

        public void Dtrsm(BlasOrderType order, BlasSideType side, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int m, int n, double alpha, double[] a, int lda, double[] b, int ldb)
        {
            SafeNativeMethods.cblas_dtrsm(order, side, uplo, transA, diag, m, n, alpha, a, lda, b, ldb);
        }

        public void Zgemm(BlasOrderType order, BlasTransType transA, BlasTransType transB, int m, int n, int k, Complex alpha, Complex[] a, int lda, Complex[] b, int ldb, Complex beta, Complex[] c, int ldc)
        {
            SafeNativeMethods.cblas_zgemm(order, transA, transB, m, n, k, ref alpha, a, lda, b, ldb, ref beta, c, ldc);
        }

        public void Zsymm(BlasOrderType order, BlasSideType side, BlasUpLoType uplo, int m, int n, Complex alpha, Complex[] a, int lda, Complex[] b, int ldb, Complex beta, Complex[] c, int ldc)
        {
            SafeNativeMethods.cblas_zsymm(order, side, uplo, m, n, ref alpha, a, lda, b, ldb, ref beta, c, ldc);
        }

        public void Zsyrk(BlasOrderType order, BlasUpLoType uplo, BlasTransType trans, int n, int k, Complex alpha, Complex[] a, int lda, Complex beta, Complex[] c, int ldc)
        {
            SafeNativeMethods.cblas_zsyrk(order, uplo, trans, n, k, ref alpha, a, lda, ref beta, c, ldc);
        }

        public void Zsyr2k(BlasOrderType order, BlasUpLoType uplo, BlasTransType trans, int n, int k, Complex alpha, Complex[] a, int lda, Complex[] b, int ldb, Complex beta, Complex[] c, int ldc)
        {
            SafeNativeMethods.cblas_zsyr2k(order, uplo, trans, n, k, ref alpha, a, lda, b, ldb, ref beta, c, ldc);
        }

        public void Ztrmm(BlasOrderType order, BlasSideType side, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int m, int n, Complex alpha, Complex[] a, int lda, Complex[] b, int ldb)
        {
            SafeNativeMethods.cblas_ztrmm(order, side, uplo, transA, diag, m, n, ref alpha, a, lda, b, ldb);
        }

        public void Ztrsm(BlasOrderType order, BlasSideType side, BlasUpLoType uplo, BlasTransType transA, BlasDiagType diag, int m, int n, Complex alpha, Complex[] a, int lda, Complex[] b, int ldb)
        {
            SafeNativeMethods.cblas_ztrsm(order, side, uplo, transA, diag, m, n, ref alpha, a, lda, b, ldb);
        }

        public void Zhemm(BlasOrderType order, BlasSideType side, BlasUpLoType uplo, int m, int n, Complex alpha, Complex[] a, int lda, Complex[] b, int ldb, Complex beta, Complex[] c, int ldc)
        {
            SafeNativeMethods.cblas_zhemm(order, side, uplo, m, n, ref alpha, a, lda, b, ldb, ref beta, c, ldc);
        }

        public void Zherk(BlasOrderType order, BlasUpLoType uplo, BlasTransType trans, int n, int k, double alpha, Complex[] a, int lda, double beta, Complex[] c, int ldc)
        {
            SafeNativeMethods.cblas_zherk(order, uplo, trans, n, k, alpha, a, lda, beta, c, ldc);
        }

        public void Zher2k(BlasOrderType order, BlasUpLoType uplo, BlasTransType trans, int n, int k, Complex alpha, Complex[] a, int lda, Complex[] b, int ldb, double beta, Complex[] c, int ldc)
        {
            SafeNativeMethods.cblas_zher2k(order, uplo, trans, n, k, ref alpha, a, lda, b, ldb, beta, c, ldc);
        }

        #endregion Public Members
    }
}